package com.ats.audiotoscore;

//import android.util.Log;

public class AudioProcess extends Thread {
//	private static final String TAG = "AudioProcess";
	private double buffer[] = null;
	private boolean running = true;
	private Object lock = null;
	private PitchDetection pd;
	private MainActivity ma;
	private int sampleRate = 0;
	private long msTime = 0;
	private int lastNote = 0;
	private boolean addedNote = false;
	// The Google ASR input requirements state that audio input sensitivity
	// should be set such that 90 dB SPL at 1000 Hz yields RMS of 2500 for
	// 16-bit samples, i.e. 20 * log_10(2500 / mGain) = 90.
	private double mGain = 2500.0 / Math.pow(10.0, 90.0 / 20.0);
	private double mRmsSmoothed = 0;
	private double mAlpha = 0.9;
	private double rmsdB = 0;
	private double realRmsdB = 0;

	public AudioProcess(PitchDetection _pd, MainActivity _ma) {
		lock = new Object();
		pd = _pd;
		ma = _ma;
		start();
	}

	public void terminate() {
		running = false;
		lock.notify();
	}

	@Override
	public void run() {
		while (running) {
			try {
				synchronized (lock) {
					lock.wait();
				}
				ProcessSamples();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void UpdateSamples(double samples[], int _sampleRate, long _msTime) {
		sampleRate = _sampleRate;
		msTime = _msTime;

		if (buffer != null && buffer.length != samples.length) {
			buffer = null;
		}

		if (buffer == null) {
			buffer = new double[samples.length];
		}

		for (int i=0; i<samples.length; i++) {
			buffer[i] = samples[i];
		}

		synchronized (lock) {
			lock.notify();
		}
	}

	private void ProcessRmsdB(double[] data) {
		// Compute the RMS value. (Note that this does not remove DC).
		double rms = 0;

		for (int i = 0; i < data.length; i++) {
			rms += data[i]*data[i];
		}
		rms = Math.sqrt(rms/data.length);

		// Compute a smoothed version for less flickering of the display.
		mRmsSmoothed = mRmsSmoothed * mAlpha + (1 - mAlpha) * rms;
		realRmsdB = 20.0 * Math.log10(mGain * rms);
		rmsdB = 20.0 * Math.log10(mGain * mRmsSmoothed);
	}

	public double getRealRmsdB() {
		return realRmsdB;
	}

	public double getRmsdB() {
		return rmsdB;
	}

	private void ProcessSamples() {
		ProcessRmsdB(buffer);
		pd.UpdateSamples(buffer, sampleRate, getRealRmsdB());
// 		Log.i(TAG, "ProcessSamples detectednote="+pd.GetDetectedNote()+" confidence="+pd.GetPitchConfidence());
		if (pd.IsNoteSafe()) {
		 	if (addedNote == false || lastNote != pd.GetDetectedNote()) {
//		 		Log.i(TAG, "adding note "+pd.GetDetectedNote());
				ma.AddNote(pd.GetDetectedNote(), msTime, 250);
				addedNote = true;
				lastNote = pd.GetDetectedNote();
			}
		} else {
			if (pd.GetPitchConfidence() == 0) {
//		 		Log.i(TAG, "addednote = false");
				addedNote = false;
				lastNote = 0;
			}
		}

		ma.UpdateUI();
	}
}

